contents
데이터베이스 정규화는 관계형 데이터베이스에서 데이터 중복을 최소화하고 데이터 무결성을 향상시키기 위해 열과 테이블을 체계적으로 구성하는 과정입니다. 이는 큰 테이블을 더 작고 잘 구조화된 테이블로 나누고 그들 사이의 관계를 정의하는 것을 포함합니다.
주된 목표는 모든 데이터 조각이 단 한 곳에만 저장되도록 보장하여, 데이터가 중복될 때 발생할 수 있는 문제들을 예방하는 것입니다.
비유: 정규화를 지저분한 옷장을 정리하는 것으로 생각할 수 있습니다. 모든 것을 하나의 큰 더미에 던져 넣는 대신, 셔츠는 한 서랍에, 바지는 다른 서랍에, 양말은 세 번째 서랍에 넣고, 서로 연결되는 라벨을 붙이는 것과 같습니다. 이렇게 하면 옷을 찾고, 업데이트하고, 관리하기가 더 쉬워집니다.
왜 정규화를 하는가? 이상 현상의 문제점
정규화가 없으면 데이터베이스는 이상 현상(anomaly) 이라고 불리는 세 가지 유형의 문제에 취약해집니다.
- 삽입 이상 (Insertion Anomaly): 다른 관련 없는 정보가 누락되어 새로운 정보를 추가할 수 없는 문제입니다. 예를 들어, 대학 데이터베이스에 새로운 교수가 가르칠 과목이 배정될 때까지 그 교수의 정보를 추가할 수 없는 경우입니다.
- 갱신 이상 (Update Anomaly): 동일한 데이터 조각이 여러 행에 존재하여, 이를 업데이트하려면 모든 인스턴스를 찾아 변경해야 하는 문제입니다. 하나라도 놓치면 데이터가 불일치하게 됩니다. 예를 들어, 교수의 이름이 그가 가르치는 모든 과목과 함께 저장되어 있다면, 이름을 변경하려면 여러 행을 업데이트해야 합니다.
- 삭제 이상 (Deletion Anomaly): 하나의 정보를 삭제하면 의도치 않게 다른 관련 없는 정보까지 삭제되는 문제입니다. 예를 들어, 학생이 유일하게 수강하던 과목을 취소했을 때, 학생 정보가 수강 신청 테이블에만 저장되어 있었다면 학생의 전체 기록이 사라질 수 있습니다.
정규화는 이러한 이상 현상에 대한 치료법입니다.
정규형 ("어떻게")
정규화는 정규형(normal form) 이라고 불리는 일련의 규칙을 따름으로써 달성됩니다. 데이터베이스가 1NF의 규칙을 만족하면 "제1정규형"에 있다고 말합니다. 2NF가 되려면 먼저 1NF여야 하며, 이후 정규형도 마찬가지입니다. 대부분의 실용적인 애플리케이션에서는 제3정규형(3NF) 에 도달하는 것이 충분하다고 간주됩니다.
제1정규형 (1NF)
규칙: 테이블의 각 셀은 단일하고 원자적인(분해할 수 없는) 값을 가져야 하며, 각 레코드는 고유해야 합니다. 이는 반복되는 그룹이나 다중 값을 가진 열이 없어야 함을 의미합니다.
- 나쁜 예 (1NF 아님):
| CourseID | CourseName | Students |
|---|---|---|
| 101 | SQL 입문 | "앨리스, 밥, 찰리" |
| 102 | 고급 자바 | "앨리스, 데이빗" |
Students 열이 값의 목록을 포함하고 있으므로 1NF를 위반합니다.
- 좋은 예 (1NF): 각 셀이 원자적이 되도록 테이블을 분리합니다.
Courses 테이블:
| CourseID | CourseName |
|---|---|
| 101 | SQL 입문 |
| 102 | 고급 자바 |
Enrollments 테이블:
| CourseID | StudentName |
|---|---|
| 101 | 앨리스 |
| 101 | 밥 |
| 101 | 찰리 |
| 102 | 앨리스 |
| 102 | 데이빗 |
제2정규형 (2NF)
규칙:
- 1NF여야 합니다.
- 모든 키가 아닌 속성은 전체 기본 키에 완전 함수적으로 종속되어야 합니다.
이 규칙은 복합 기본 키(두 개 이상의 열로 구성된 기본 키)를 가진 테이블에만 적용됩니다. 이는 키가 아닌 열이 복합 키의 _일부_에만 종속되어서는 안 된다는 것을 의미합니다.
- 나쁜 예 (2NF 아님): 기본 키가 (OrderID, ProductID)인 테이블을 상상해 보세요.
| OrderID | ProductID | ProductName | Quantity |
|---|---|---|---|
| 1 | 10 | 노트북 | 1 |
| 1 | 25 | 마우스 | 2 |
| 2 | 10 | 노트북 | 1 |
여기서 ProductName은 전체 (OrderID, ProductID) 키가 아닌 ProductID에만 종속됩니다. 이는 부분 종속성입니다.
- 좋은 예 (2NF): 부분적으로 종속된 열을 자체 테이블로 옮깁니다.
OrderDetails 테이블:
| OrderID | ProductID | Quantity |
|---|---|---|
| 1 | 10 | 1 |
| 1 | 25 | 2 |
| 2 | 10 | 1 |
Products 테이블:
| ProductID | ProductName |
|---|---|
| 10 | 노트북 |
| 25 | 마우스 |
제3정규형 (3NF)
규칙:
- 2NF여야 합니다.
- 이행적 종속성(transitive dependency) 이 없어야 합니다. 이행적 종속성은 키가 아닌 속성이 다른 키가 아닌 속성에 종속될 때 발생합니다.
- 나쁜 예 (3NF 아님):
| EmployeeID | Name | DepartmentID | DepartmentName |
|---|---|---|---|
| 1 | 앨리스 | 10 | 영업부 |
| 2 | 밥 | 20 | 엔지니어링 |
| 3 | 찰리 | 10 | 영업부 |
여기서 DepartmentName은 키가 아닌 속성인 DepartmentID에 종속됩니다. 이는 이행적 종속성입니다: EmployeeID → DepartmentID → DepartmentName.
- 좋은 예 (3NF): 이행적으로 종속된 속성을 자체 테이블로 옮깁니다.
Employees 테이블:
| EmployeeID | Name | DepartmentID |
|---|---|---|
| 1 | 앨리스 | 10 |
| 2 | 밥 | 20 |
| 3 | 찰리 | 10 |
Departments 테이블:
| DepartmentID | DepartmentName |
|---|---|
| 10 | 영업부 |
| 20 | 엔지니어링 |
3NF 이상
보이스-코드 정규형(BCNF), 4NF, 5NF와 같은 더 높은 정규형도 있지만, 이들은 더 복잡하고 드문 데이터 시나리오를 다룹니다. 대부분의 데이터베이스 설계에서는 3NF를 달성하는 것이 표준이자 충분한 목표입니다.
비정규화: 성능을 위한 트레이드오프 🚀
비정규화(Denormalization) 는 읽기 성능을 향상시키기 위해 의도적으로 정규화 규칙을 위반하는 과정입니다.
정규화는 더 많은 테이블로 이어지며, 데이터를 검색하기 위해 종종 더 많은 JOIN 연산이 필요합니다. 조인은 계산 비용이 많이 들 수 있습니다. 읽기 중심의 시스템(데이터 웨어하우스나 보고용 데이터베이스 등)에서는, 일반적인 쿼리에 필요한 조인 수를 줄이기 위해 중복 데이터를 테이블에 다시 추가함으로써 성능을 향상시킬 수 있습니다.
이는 트레이드오프입니다. 더 빠른 읽기를 위해 약간의 데이터 무결성을 희생하고 쓰기 복잡성을 증가시키는 것입니다.
references